package net.sk.web;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;


import net.bat.db.BaseDAOImpl;
import net.bat.util.Cfg;
import net.cs.um.UMService;
import net.sk.pt.IConsumer;
import net.sk.pt.IDistributor;
import net.sk.pt.IFilter;
import net.sk.pt.IProvider;
import net.sk.pt.IStateCenter;
import net.sk.pt.State;
import net.sk.pt.StateUtil;
import net.sk.ws.WSket;

public class StateCenter implements IStateCenter {
	public static final String PR_PR_DAO = "PR_DAO";
	public static final String PR_SYS_END = "PR_SYS_END";
	public static final String PR_SYS_MSG = "PR_SYS_MSG";
	public static final String PR_SYS_HEART = "PR_SYS_HEART";
	public static final String PR_SYS_SUBSCRIBE = "PR_SYS_SUBSCRIBE";
	
	public static final String CN_NODE_PR = "CN_NODE_PR"; 
	public static final String CN_NODE_CS = "CN_NODE_CS"; 
	public static final String CN_NODE_SE = "CN_NODE_SE"; 

	public static final String CN_NODE_DB = "CN_NODE_DT"; 
	public static final String CN_EDGE = "CN_EDGE"; 
	public static final String CN_EDGE_SPLIT = ";"; 
	
	public static final String DAO_LOCATION = "dao.hb.OLocation";
	public static final String DAO_DEVICE = "dao.hb.ODevice";
	public static final String DAO_DeviceType = "dao.hb.ODeviceType";
	public static final String DAO_OAttachment = "dao.hb.OAttachment";
	
	
	static private BaseDAOImpl dao = null;
	static private State STATE_END=null;
	
	HashMap<Object,IConsumer> consumers;
	HashMap<Object,IProvider> providers;
	HashMap<Object,IDistributor> distributors;
	HashMap<Object,HashMap<Object,IProvider>> consumer_providers;
	HashMap<Object,HashMap<Object,WSket>> session_ws;
 	
	public HashMap<Object,WSket> getWSMap(Object skey){
		return session_ws.get(skey);
	}
	public void ws_open(String session_key,WSket ws){
		addConsumer(ws);
		HashMap<Object,WSket> wsmap = session_ws.get(session_key);
		//新的session，添加session节点
		if(wsmap==null){
			wsmap = new HashMap<Object,WSket>();
			wsmap.put(ws.getKey(), ws);
			session_ws.put(session_key, wsmap);
			Integer userid = UMService.getUidBySid((String)session_key);
			String skey = userid==null? session_key:session_key+CN_EDGE_SPLIT+userid;
			SendSubscirbeNode(State.ACTION_ADD,CN_NODE_SE,skey);
		}
		//增加session和ws的连线
		SendSubscirbeNode(State.ACTION_ADD,CN_EDGE,getCSPRKey(ws.getKey(),session_key));
	}
	
	public void ws_close(Object session_key,WSket ws){
		removeConsumer(ws);
		HashMap<Object,WSket> wsmap = session_ws.get(session_key);
		//新的session，添加session节点
		if(wsmap!=null){
			wsmap.remove(ws.getKey());
			if(wsmap.isEmpty()){
				session_ws.remove(session_key);
				SendSubscirbeNode(State.ACTION_REMOVE,CN_NODE_SE,session_key);
			}
		}		
		SendSubscirbeNode(State.ACTION_REMOVE,CN_EDGE,getCSPRKey(ws.getKey(),session_key));
	}
	static public State getStateEnd(){
		if(STATE_END==null){
			State s = new State();
			s.setCn(PR_SYS_END);
			s.setAction(State.ACTION_PUT);
			s.setKey(null);
			STATE_END =s;
		}
		return STATE_END;
	}
	private void SendSubscirbeNode(char action,String cn,Object key){
		State s = new State();
		s.setCn(cn);
		s.setKey(key);
		s.setAction(action);
		getProvider_Subscribe().send(s);
	}

	public IProvider getProvider_Subscribe(){
		IProvider pr= getProvider(PR_SYS_SUBSCRIBE);
		if(pr==null){
			pr = new Provider(new Keeper(),PR_SYS_SUBSCRIBE);
			addProvider(pr);			
		}
		return pr;
	}
	public IProvider getProvider(Object key){
		return providers.get(key);
	}
	public IDistributor getDistributor(Object key){
		return distributors.get(key);
	}
	public void provideState(Object key,State s){
		IProvider pr = getProvider(key);
		if(pr!= null)
			pr.send(s);
	}
	public void distributeState(Object key,State s){
		IDistributor dr = getDistributor(key);
		if(dr!=null)
			dr.send(s);
	}
	static public BaseDAOImpl getDao() {
		if (dao == null)
			dao = (BaseDAOImpl) Cfg.getBean("BaseDAOImpl");
		return dao;
	}

	private void loadDao(String cn,Provider pr){
		List ls = getDao().find("from " + cn + " where status=1");
		int len = ls.size();
		for(int i=0; i<len; i++){
			Object cur = ls.get(i);
			State s = StateUtil.obj2sta(cur, null, State.ACTION_ADD);
			pr.send(s);
		}
	}
	void buildPRDAO(){
		Provider pr = new Provider(new Keeper(),PR_PR_DAO);
		addProvider(pr);
		loadDao(DAO_LOCATION,pr);
		loadDao(DAO_DEVICE,pr);
		loadDao(DAO_DeviceType,pr);
		loadDao(DAO_OAttachment,pr);
	}
	@Override
	public void init() {
		// TODO Auto-generated method stub
		consumers = new HashMap<Object,IConsumer>();
		providers = new HashMap<Object,IProvider>();
		distributors = new HashMap<Object,IDistributor>();
		consumer_providers = new HashMap<Object,HashMap<Object,IProvider>>();
		session_ws = new HashMap<Object,HashMap<Object,WSket>> ();
		
		//buildPRDAO();
		Provider pr_msg = new Provider(new Keeper(),PR_SYS_MSG);
		Provider pr_heart = new Provider(new Keeper(),PR_SYS_HEART);
		addProvider(pr_msg);
		addProvider(pr_heart);
        HeartThread qth = new HeartThread(pr_heart);
		Thread th = new Thread(qth);
		th.start();

	}


	public void sendSysMsg(Object key,String msg){
		State s = new State();
		s.setCn(PR_SYS_MSG);
		if(key!=null){
			s.setKey(key);
		}
		if(msg!=null){
			HashMap<String,Object> its = new HashMap<String,Object>();
			its.put("content", msg);
			its.put("time", new Date().getTime());
			its.put("uname", "系统");
			s.setItems(its);
		}
		s.setAction(State.ACTION_PUT);
		provideState(PR_SYS_MSG,s);
	}
	@Override
	public void destory() {
		// TODO Auto-generated method stub
		Iterator<Entry<Object, IConsumer>> iter1 = consumers.entrySet().iterator(); 
		while (iter1.hasNext()) { 
			Entry<Object, IConsumer> entry = iter1.next(); 
			IConsumer cur = entry.getValue(); 
			cur.destory();
		} 	
		consumers.clear();
		
		Iterator<Entry<Object, IProvider>> iter2 = providers.entrySet().iterator(); 
		while (iter2.hasNext()) { 
			Entry<Object, IProvider> entry = iter2.next(); 
			IProvider cur = entry.getValue(); 
			cur.destory();
		} 	
		providers.clear();
		
		Iterator<Entry<Object, IDistributor>> iter3 = distributors.entrySet().iterator(); 
		while (iter3.hasNext()) { 
			Entry<Object, IDistributor> entry = iter3.next(); 
			IDistributor cur = entry.getValue(); 
			cur.destory();
		} 	
		consumers.clear();
	}

	public HashMap<Object,IProvider> getConsumerProviders(Object cskey){
		 HashMap<Object,IProvider> pr_map = consumer_providers.get(cskey);
		 if(pr_map==null){
			 pr_map = new HashMap<Object,IProvider>();
			 consumer_providers.put(cskey, pr_map);
		 }
		 return pr_map;
	}
	public void unSubscribeProvider(IConsumer cs,String prn){
		IProvider pr = getProvider(prn);
		if(pr!=null){
			pr.removeConsumer(cs);
			getConsumerProviders(cs.getKey()).remove(pr.getKey());
			SendSubscirbeNode(State.ACTION_REMOVE,CN_EDGE,getCSPRKey(cs.getKey(),pr.getKey()));
		}
	}
	public String getCSPRKey(Object cskey,Object prkey){
		return cskey+CN_EDGE_SPLIT+prkey;
	}
	public void unSubscribeProvider(IConsumer cs,String[] prs){
		for(int i=0; i<prs.length; i++){
			unSubscribeProvider(cs,prs[i]);
		}
	}
	public void subscribeProvider(IConsumer cs,String prn,IFilter fl){
		IProvider pr = getProvider(prn);
		if(pr!=null){
			pr.addConsumer(cs, fl);
			getConsumerProviders(cs.getKey()).put(pr.getKey(), pr);
			SendSubscirbeNode(State.ACTION_ADD,CN_EDGE,getCSPRKey(cs.getKey(),pr.getKey()));
		}
	}
	
	public void subscribeProvider(IConsumer cs,String[]prs,IFilter[] filters){
		for(int i=0; i<prs.length; i++){
			if(filters!=null){
				subscribeProvider(cs,prs[i],filters[i]);
			}else{
				subscribeProvider(cs,prs[i],null);
			}
		}
	}
	@Override
	public void addConsumer(IConsumer cs) {
		// TODO Auto-generated method stub
		consumers.put(cs.getKey(), cs);
		SendSubscirbeNode(State.ACTION_ADD,CN_NODE_CS,cs.getKey());
	}

	@Override
	public void removeConsumer(IConsumer cs) {
		// TODO Auto-generated method stub
		Object cskey = cs.getKey();
		consumers.remove(cskey);
		getProvider_Subscribe().removeConsumer(cs);
		
		SendSubscirbeNode(State.ACTION_REMOVE,CN_NODE_CS,cskey);
		
		HashMap<Object,IProvider> cpr = consumer_providers.get(cskey);
		if(cpr==null){
			return;
		}
		Iterator<Entry<Object,IProvider>> iter = cpr.entrySet().iterator(); 
		while (iter.hasNext()) { 
			Entry<Object,IProvider> entry = iter.next(); 
			IProvider pr = entry.getValue(); 
			pr.removeConsumer(cs);
			SendSubscirbeNode(State.ACTION_REMOVE,CN_EDGE,getCSPRKey(cs.getKey(),pr.getKey()));
		} 	
		cpr.clear();
		consumer_providers.remove(cskey);
		//cs.destory();
		
	}

	@Override
	public void addProvider(IProvider pr) {
		// TODO Auto-generated method stub
		providers.put(pr.getKey(), pr);
		SendSubscirbeNode(State.ACTION_ADD,CN_NODE_PR,pr.getKey());
	}

	@Override
	public void removeProvider(IProvider pr) {
		// TODO Auto-generated method stub
		providers.remove(pr.getKey());
		SendSubscirbeNode(State.ACTION_REMOVE,CN_NODE_PR,pr.getKey());
		HashMap<Object,IConsumer> css = pr.getConsumers();
		if(css!=null){
			Iterator<Entry<Object,IConsumer>> iter =css.entrySet().iterator(); 
			while (iter.hasNext()) { 
				Entry<Object,IConsumer> entry = iter.next(); 
				IConsumer cs = entry.getValue(); 
				getConsumerProviders(cs.getKey()).remove(pr.getKey());
				SendSubscirbeNode(State.ACTION_REMOVE,CN_EDGE,getCSPRKey(cs.getKey(),pr.getKey()));
			} 	
		}
		pr.destory();
	}

	@Override
	public void addDistributor(IDistributor db) {
		// TODO Auto-generated method stub
		distributors.put(db.getKey(), db);
		SendSubscirbeNode(State.ACTION_ADD,CN_NODE_DB,db.getKey());
	}

	@Override
	public void removeDistributor(IDistributor db) {
		// TODO Auto-generated method stub
		distributors.remove(db.getKey());
		SendSubscirbeNode(State.ACTION_REMOVE,CN_NODE_DB,db.getKey());
		//db.destory();
	}
	@Override
	public IConsumer getConsumer(Object key) {
		// TODO Auto-generated method stub
		return consumers.get(key);
	}

}
